#include "Knight.h"

#include "SquareValueBoard.h"

using namespace Rorn::Chess::TheCorruptRook;

Knight::Knight(void)
{
}

Knight::~Knight(void)
{
}

/*static*/ double Knight::CalculateScore(const Position& position, Player::Type player, const Square& square)
{
	double materialScore = 3.0;

	std::vector<Square> visibleAttackSquares;
	GetVisibleAttackSquares(position, player, square, visibleAttackSquares);
	double visibilityScore = 0;
	for(std::vector<Square>::const_iterator sqaureIter = visibleAttackSquares.begin() ; sqaureIter != visibleAttackSquares.end() ; ++sqaureIter)
		visibilityScore += SquareValueBoard::GetSquareValue(*sqaureIter);

	return materialScore + visibilityScore;
}

/*static*/ void Knight::GetLegalMoves(const Position& position, Player::Type player, const Square& startSquare, std::vector<MoveTreeNode>& legalMoves, int depth)
{
	Square squareNNE(startSquare.GetRank() + 2, startSquare.GetFile() + 1);
	if( Square::IsOnBoard(squareNNE) &&
		(position.GetPiece(player, squareNNE) <= 0) )
	{
		legalMoves.emplace_back(MoveTreeNode(position, Player::GetOpposite(player), depth, startSquare, squareNNE));
	}

	Square squareENE(startSquare.GetRank() + 1, startSquare.GetFile() + 2);
	if( Square::IsOnBoard(squareENE) &&
		(position.GetPiece(player, squareENE) <= 0) )
	{
		legalMoves.emplace_back(MoveTreeNode(position, Player::GetOpposite(player), depth, startSquare, squareENE));
	}

	Square squareESE(startSquare.GetRank() - 1, startSquare.GetFile() + 2);
	if( Square::IsOnBoard(squareESE) &&
		(position.GetPiece(player, squareESE) <= 0) )
	{
		legalMoves.emplace_back(MoveTreeNode(position, Player::GetOpposite(player), depth, startSquare, squareESE));
	}

	Square squareSSE(startSquare.GetRank() - 2, startSquare.GetFile() + 1);
	if( Square::IsOnBoard(squareSSE) &&
		(position.GetPiece(player, squareSSE) <= 0) )
	{
		legalMoves.emplace_back(MoveTreeNode(position, Player::GetOpposite(player), depth, startSquare, squareSSE));
	}

	Square squareSSW(startSquare.GetRank() - 2, startSquare.GetFile() - 1);
	if( Square::IsOnBoard(squareSSW) &&
		(position.GetPiece(player, squareSSW) <= 0) )
	{
		legalMoves.emplace_back(MoveTreeNode(position, Player::GetOpposite(player), depth, startSquare, squareSSW));
	}

	Square squareWSW(startSquare.GetRank() - 1, startSquare.GetFile() - 2);
	if( Square::IsOnBoard(squareWSW) &&
		(position.GetPiece(player, squareWSW) <= 0) )
	{
		legalMoves.emplace_back(MoveTreeNode(position, Player::GetOpposite(player), depth, startSquare, squareWSW));
	}

	Square squareWNW(startSquare.GetRank() + 1, startSquare.GetFile() - 2);
	if( Square::IsOnBoard(squareWNW) &&
		(position.GetPiece(player, squareWNW) <= 0) )
	{
		legalMoves.emplace_back(MoveTreeNode(position, Player::GetOpposite(player), depth, startSquare, squareWNW));
	}

	Square squareNNW(startSquare.GetRank() + 2, startSquare.GetFile() - 1);
	if( Square::IsOnBoard(squareNNW) &&
		(position.GetPiece(player, squareNNW) <= 0) )
	{
		legalMoves.emplace_back(MoveTreeNode(position, Player::GetOpposite(player), depth, startSquare, squareNNW));
	}
}

/*static*/ void Knight::GetVisibleAttackSquares(const Position& position, Player::Type player, const Square& square, std::vector<Square>& visibleAttackSquares)
{
	Square squareNNE(square.GetRank() + 2, square.GetFile() + 1);
	if( Square::IsOnBoard(squareNNE) &&
		(position.GetPiece(player, squareNNE) <= 0) )
	{
		visibleAttackSquares.push_back(squareNNE);
	}

	Square squareENE(square.GetRank() + 1, square.GetFile() + 2);
	if( Square::IsOnBoard(squareENE) &&
		(position.GetPiece(player, squareENE) <= 0) )
	{
		visibleAttackSquares.push_back(squareENE);
	}

	Square squareESE(square.GetRank() - 1, square.GetFile() + 2);
	if( Square::IsOnBoard(squareESE) &&
		(position.GetPiece(player, squareESE) <= 0) )
	{
		visibleAttackSquares.push_back(squareESE);
	}

	Square squareSSE(square.GetRank() - 2, square.GetFile() + 1);
	if( Square::IsOnBoard(squareSSE) &&
		(position.GetPiece(player, squareSSE) <= 0) )
	{
		visibleAttackSquares.push_back(squareSSE);
	}

	Square squareSSW(square.GetRank() - 2, square.GetFile() - 1);
	if( Square::IsOnBoard(squareSSW) &&
		(position.GetPiece(player, squareSSW) <= 0) )
	{
		visibleAttackSquares.push_back(squareSSW);
	}

	Square squareWSW(square.GetRank() - 1, square.GetFile() - 2);
	if( Square::IsOnBoard(squareWSW) &&
		(position.GetPiece(player, squareWSW) <= 0) )
	{
		visibleAttackSquares.push_back(squareWSW);
	}

	Square squareWNW(square.GetRank() + 1, square.GetFile() - 2);
	if( Square::IsOnBoard(squareWNW) &&
		(position.GetPiece(player, squareWNW) <= 0) )
	{
		visibleAttackSquares.push_back(squareWNW);
	}

	Square squareNNW(square.GetRank() + 2, square.GetFile() - 1);
	if( Square::IsOnBoard(squareNNW) &&
		(position.GetPiece(player, squareNNW) <= 0) )
	{
		visibleAttackSquares.push_back(squareNNW);
	}
}